﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LoA.Shared.Screen;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace LoA.Screen {
	public partial class ScreenManager : DrawableGameComponent {
		public override void Update(GameTime gameTime) {
			KeyboardState currentKeyboardState = Keyboard.GetState( );
			GamePadState currentGamePadState = GamePad.GetState(PlayerIndex.One);

			if (currentKeyboardState != previousCurrentKeyboardState) {
				if (this.GameState != GameState.Playing) {
					switch (GameState) {
						case GameState.NotStarted:
							if ((currentGamePadState.IsButtonDown(Buttons.DPadUp) && previousCurrentGamePadSate.IsButtonUp(Buttons.DPadUp)) ||
								(currentKeyboardState.IsKeyDown(Keys.Up) && previousCurrentKeyboardState.IsKeyUp(Keys.Up)))
								this.SelectPrevious( );
							if ((currentGamePadState.IsButtonDown(Buttons.DPadDown) && previousCurrentGamePadSate.IsButtonUp(Buttons.DPadDown)) ||
								(currentKeyboardState.IsKeyDown(Keys.Down) && previousCurrentKeyboardState.IsKeyUp(Keys.Down)))
								this.SelectNext( );
							if ((currentGamePadState.IsButtonDown(Buttons.DPadLeft) && previousCurrentGamePadSate.IsButtonUp(Buttons.DPadLeft)) ||
								(currentKeyboardState.IsKeyDown(Keys.Left) && previousCurrentKeyboardState.IsKeyUp(Keys.Left)))
								this.DecrementSelected( );
							if ((currentGamePadState.IsButtonDown(Buttons.DPadRight) && previousCurrentGamePadSate.IsButtonUp(Buttons.DPadRight)) ||
								(currentKeyboardState.IsKeyDown(Keys.Right) && previousCurrentKeyboardState.IsKeyUp(Keys.Right)))
								this.IncrementSelected( );
							if ((currentGamePadState.IsButtonDown(Buttons.A) && previousCurrentGamePadSate.IsButtonUp(Buttons.A)) ||
								(currentKeyboardState.IsKeyDown(Keys.Space) && previousCurrentKeyboardState.IsKeyUp(Keys.Space)) ||
								(currentKeyboardState.IsKeyDown(Keys.Enter) && previousCurrentKeyboardState.IsKeyUp(Keys.Enter)))
								this.Enter( );
							if ((currentGamePadState.IsButtonDown(Buttons.B) && previousCurrentGamePadSate.IsButtonUp(Buttons.B)) ||
								(currentKeyboardState.IsKeyDown(Keys.Escape) && previousCurrentKeyboardState.IsKeyUp(Keys.Escape)))
								this.Cancel( );
							break;
						case GameState.Suspended:
							if ((currentGamePadState.IsButtonDown(Buttons.A) && previousCurrentGamePadSate.IsButtonUp(Buttons.A)) ||
								(currentKeyboardState.IsKeyDown(Keys.Space) && previousCurrentKeyboardState.IsKeyUp(Keys.Space)) ||
								(currentKeyboardState.IsKeyDown(Keys.Enter) && previousCurrentKeyboardState.IsKeyUp(Keys.Enter)))
								this.Enter( );
							if ((currentGamePadState.IsButtonDown(Buttons.B) && previousCurrentGamePadSate.IsButtonUp(Buttons.B)) ||
								(currentKeyboardState.IsKeyDown(Keys.Escape) && previousCurrentKeyboardState.IsKeyUp(Keys.Escape)))
								this.Cancel( );
							break;
					}
				} else {
					if (currentKeyboardState.IsKeyDown(Keys.Escape) && previousCurrentKeyboardState.IsKeyUp(Keys.Escape)) {
						this.ShowPopup(suspendPopup);
					}
				}
				this.previousCurrentKeyboardState = currentKeyboardState;
				this.previousCurrentGamePadSate = currentGamePadState;
			}

			base.Update(gameTime);
		}

		private void ShowPopup(IPopupScreenEntry suspendPopup) {
			if (GameState == GameState.Playing) {
				this.GameState = GameState.Suspending;
				this.Visible = true;
				GameLoader.Suspend( );
			}
			this.popupsTrace.Push(suspendPopup);
			if (GameState == GameState.Suspending)
				this.GameState = GameState.Suspended;
		}

		private void IncrementSelected( ) {
			if (this.currentPopup != null) {

			} else if (0 <= selectedEntry && selectedEntry < currentScreen.Entries.Count( )) {
				IScreenEntry genericItem = currentScreen.Entries.ElementAt(this.selectedEntry);
				if (genericItem is IChangeableScreenEntry) {
					IChangeableScreenEntry item = genericItem as IChangeableScreenEntry;
					item.SelectedIndex++;
				}
			}
		}

		private void DecrementSelected( ) {
			if (this.currentPopup != null) {

			} else if (0 <= selectedEntry && selectedEntry < currentScreen.Entries.Count( )) {
				IScreenEntry genericItem = currentScreen.Entries.ElementAt(this.selectedEntry);
				if (genericItem is IChangeableScreenEntry) {
					IChangeableScreenEntry item = genericItem as IChangeableScreenEntry;
					item.SelectedIndex--;
				}
			}
		}

		private void Enter( ) {
			if (this.currentPopup != null) {
				var popup = this.popupsTrace.Pop( );
				this.RunAction(popup.Action);
			} else if (0 <= selectedEntry && selectedEntry < currentScreen.Entries.Count( )) {
				IScreenEntry genericItem = currentScreen.Entries.ElementAt(this.selectedEntry);
				if (genericItem is IPopupScreenEntry) {
					IPopupScreenEntry item = genericItem as IPopupScreenEntry;
					this.popupsTrace.Push(item);
				} else if (genericItem is ILinkScreenEntry) {
					ILinkScreenEntry item = genericItem as ILinkScreenEntry;
					this.entriesTrace.Push(selectedEntry);
					this.screensTrace.Push(item.NextScreen);
					this.selectedEntry = 0;
				} else if (genericItem is IActionScreenEntry) {
					IActionScreenEntry item = genericItem as IActionScreenEntry;
					// Waht happen with menu state?
					//this.screensTrace.Push(selectedEntry);
					//this.currentScreen = item.NextScreen;
					//this.selectedEntry = 0;
					this.RunAction(item.Action);
				}
			}
		}

		private void Cancel( ) {
			if (this.currentPopup != null) {
				this.RunAction(EntryAction.CloseWindow);
			} else if (this.screensTrace.Count > 0)
				this.RunAction(EntryAction.BackMenu);
		}

		private void SelectNext( ) {
			if (this.currentPopup != null) {

			} else if (this.selectedEntry < currentScreen.Entries.Count( ) - 1)
				this.selectedEntry++;
		}

		private void SelectPrevious( ) {
			if (this.currentPopup != null) {

			} else if (this.selectedEntry > 0)
				this.selectedEntry--;
		}

		private void RunAction(EntryAction Action) {
			switch (Action) {
				case EntryAction.ExitGame:
					Game.Exit( );
					break;
				case EntryAction.QuitMenu:
					this.Visible = false;
					break;
				case EntryAction.CloseWindow:
					this.popupsTrace.Pop( );
					if (this.GameState == GameState.Suspended && this.popupsTrace.Count == 0) {
						this.RunAction(EntryAction.PlayGame);
					}
					break;
				case EntryAction.PlayGame:
					if (this.GameState == GameState.NotStarted) {
						this.GameState = GameState.Loading;
					} else {
						this.GameState = GameState.Resuming;
					}
					GameLoader.LoadTo(this.Game.Components);
					if (this.GameState == GameState.Loading) {
						GameLoader.Initialize( );
					} else {
						GameLoader.Resume( );
					}
					this.Visible = false;
					this.GameState = GameState.Playing;
					break;
				case EntryAction.BackMenu:
					if (this.screensTrace.Count > 0) {
						this.screensTrace.Pop( );
						this.selectedEntry = this.entriesTrace.Pop( );
					}
					break;
				case EntryAction.OpenMenu:
					this.GameState = GameState.Closeing;
					GameLoader.UnloadFrom(this.Game.Components);
					this.GameState = GameState.NotStarted;
					break;
			}
		}
	}
}
